package org.jvm.rtda.thread;

import org.jvm.rtda.heap.classmember.Method;

/**
 * 栈帧，持有方法的本地变量表和操作数栈
 *
 * @author 海燕
 * @date 2023/1/12
 */
public class Frame {

    @Override
    public String toString() {
        return "\n" + method;
    }

    /**
     * 本地变量表
     */
    private LocalVars localVars;

    /**
     * 操作数栈
     */
    private OperandStack operandStack;

    /**
     * 帧所在线程
     */
    private Thread thread;

    /**
     * 这里是记录本栈帧的程序计数器的位置用的
     * 当本栈帧顶上的一个栈帧被弹出后，线程需要读取本栈帧的执行位置，
     */
    private int nextPC;

    /**
     * 栈帧所对应的方法
     */
    private Method method;

    public LocalVars getLocalVars() {
        return localVars;
    }

    public void setLocalVars(LocalVars localVars) {
        this.localVars = localVars;
    }

    public OperandStack getOperandStack() {
        return operandStack;
    }

    public void setOperandStack(OperandStack operandStack) {
        this.operandStack = operandStack;
    }

    public Thread getThread() {
        return thread;
    }

    public void setThread(Thread thread) {
        this.thread = thread;
    }

    public int getNextPC() {
        return nextPC;
    }

    public void setNextPC(int nextPC) {
        this.nextPC = nextPC;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Frame(Thread thread, Method method) {
        this.thread = thread;
        this.method = method;
        this.localVars = new LocalVars(method.getMaxLocals());
        this.operandStack = new OperandStack(method.getMaxStack());
    }

    public Frame() {
    }

    /**
     * 如果在指令执行中终止执行（类初始化过程），栈帧中的nextPC已经指向了下一个指令
     * 这里重置nextPC，将其重新指向执行中指令
     */
    public void revertNextPC() {
        this.nextPC = this.thread.getPc();
    }
}
